package com.ttyec.park.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.ttyec.park.bean.HandShakeBean;
import com.ttyec.park.bean.MsgDataBean;
import com.ttyec.park.bean.PulseBean;
import com.ttyec.park.exp.RedirectException;
import com.ttyec.park.utils.LogUtils;
import com.xuhao.didi.core.iocore.interfaces.IPulseSendable;
import com.xuhao.didi.core.iocore.interfaces.ISendable;
import com.xuhao.didi.core.pojo.OriginalData;
import com.xuhao.didi.socket.client.impl.client.action.ActionDispatcher;
import com.xuhao.didi.socket.client.sdk.OkSocket;
import com.xuhao.didi.socket.client.sdk.client.ConnectionInfo;
import com.xuhao.didi.socket.client.sdk.client.OkSocketOptions;
import com.xuhao.didi.socket.client.sdk.client.action.SocketActionAdapter;
import com.xuhao.didi.socket.client.sdk.client.connection.IConnectionManager;
import com.xuhao.didi.socket.client.sdk.client.connection.NoneReconnect;

import java.nio.charset.Charset;
import java.util.Arrays;

public class SocketService extends Service {
    private IConnectionManager mManager;
    private ConnectionInfo mInfo;

    private MyBinder myBinder = new MyBinder();

    private String ip = "104.238.184.237"; // 默认测试ip
    private int port = 8080; // 默认测试port

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }

    public class MyBinder extends Binder {
        public SocketService getService() {
            // 返回当前对象LocalService,这样我们就可在客户端端调用Service的公共方法了
            return SocketService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        init();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            if (intent.hasExtra("ip") && !TextUtils.isEmpty(intent.getStringExtra("ip"))) {
                ip = intent.getStringExtra("ip");
            }
            if (intent.hasExtra("port")) {
                port = intent.getIntExtra("port", 8080);
            }
        }
        startSocket();
        return super.onStartCommand(intent, flags, startId);
    }

    private void startSocket() {
        if (mManager == null) {
            return;
        }
        if (!mManager.isConnect()) {
            mManager.connect();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    private void init() {
        mInfo = new ConnectionInfo(ip, port);
        final Handler handler = new Handler(Looper.getMainLooper());
        OkSocketOptions.Builder builder = new OkSocketOptions.Builder();
        builder.setReconnectionManager(new NoneReconnect());
        builder.setCallbackThreadModeToken(new OkSocketOptions.ThreadModeToken() {
            @Override
            public void handleCallbackEvent(ActionDispatcher.ActionRunnable runnable) {
                handler.post(runnable);
            }
        });
        mManager = OkSocket.open(mInfo).option(builder.build());
        mManager.registerReceiver(adapter);
    }

    private SocketActionAdapter adapter = new SocketActionAdapter() {

        @Override
        public void onSocketConnectionSuccess(ConnectionInfo info, String action) {
            logRece("连接成功(Connecting Successful)");
            Log.i("cme", "onSocketConnectionSuccess : ");
            mManager.send(new HandShakeBean());
            initSwitch();
            mManager.getPulseManager().setPulseSendable(new PulseBean());
        }

        private void initSwitch() {
            if (mManager.getReconnectionManager() instanceof NoneReconnect) {
                mManager.option(new OkSocketOptions.Builder(mManager.getOption()).setReconnectionManager(OkSocketOptions.getDefault().getReconnectionManager()).build());
                logSend("打开重连管理器(Turn On The Reconnection Manager)");
            }
        }

        @Override
        public void onSocketDisconnection(ConnectionInfo info, String action, Exception e) {
            Log.i("cme", "onSocketDisconnection : ");
            if (e != null) {
                if (e instanceof RedirectException) {
                    logSend("正在重定向连接(Redirect Connecting)...");
                    mManager.switchConnectionInfo(((RedirectException) e).redirectInfo);
                    mManager.connect();
                } else {
                    logSend("异常断开(Disconnected with exception):" + e.getMessage());
                }
            } else {
                logSend("正常断开(Disconnect Manually)");
            }
        }

        @Override
        public void onSocketConnectionFailed(ConnectionInfo info, String action, Exception e) {
            logSend("连接失败(Connecting Failed)");
            Log.i("cme", "onSocketConnectionFailed : ");
        }

        @Override
        public void onSocketReadResponse(ConnectionInfo info, String action, OriginalData data) {
            String str = new String(data.getBodyBytes(), Charset.forName("utf-8"));
            Log.i("cme", "onSocketReadResponse : " + str);
            JsonObject jsonObject = new JsonParser().parse(str).getAsJsonObject();
            int cmd = jsonObject.get("cmd").getAsInt();
            if (cmd == 54) {//登陆成功
                String handshake = jsonObject.get("handshake").getAsString();
                logRece("握手成功! 握手信息(Handshake Success):" + handshake + ". 开始心跳(Start Heartbeat)..");
            } else if (cmd == 57) {//切换,重定向.(暂时无法演示,如有疑问请咨询github)
                String ip = jsonObject.get("data").getAsString().split(":")[0];
                int port = Integer.parseInt(jsonObject.get("data").getAsString().split(":")[1]);
                ConnectionInfo redirectInfo = new ConnectionInfo(ip, port);
                redirectInfo.setBackupInfo(mInfo.getBackupInfo());
                mManager.getReconnectionManager().addIgnoreException(RedirectException.class);
                mManager.disconnect(new RedirectException(redirectInfo));
            } else if (cmd == 14) {//心跳
                logRece("收到心跳,喂狗成功(Heartbeat Received,Feed the Dog)");
                mManager.getPulseManager().feed();
            } else {
                logRece(str);
            }
        }

        @Override
        public void onSocketWriteResponse(ConnectionInfo info, String action, ISendable data) {
            byte[] bytes = data.parse();
            bytes = Arrays.copyOfRange(bytes, 4, bytes.length);
            String str = new String(bytes, Charset.forName("utf-8"));
            Log.i("cme", "onSocketWriteResponse : " + str);
            JsonObject jsonObject = new JsonParser().parse(str).getAsJsonObject();
            int cmd = jsonObject.get("cmd").getAsInt();
            switch (cmd) {
                case 54: {
                    String handshake = jsonObject.get("handshake").getAsString();
                    logSend("发送握手数据(Handshake Sending):" + handshake);
                    mManager.getPulseManager().pulse();
                    break;
                }
                default:
                    logSend(str);
            }
        }

        @Override
        public void onPulseSend(ConnectionInfo info, IPulseSendable data) {
            byte[] bytes = data.parse();
            bytes = Arrays.copyOfRange(bytes, 4, bytes.length);
            String str = new String(bytes, Charset.forName("utf-8"));
            Log.i("cme", "发送心跳：" + str);
            JsonObject jsonObject = new JsonParser().parse(str).getAsJsonObject();
            int cmd = jsonObject.get("cmd").getAsInt();
            if (cmd == 14) {
                logSend("发送心跳包(Heartbeat Sending)");
            }
        }
    };

    private void logSend(String log) {
        LogUtils.i("发送消息：" + log);
    }

    private void logRece(String log) {
        LogUtils.i("接收消息：" + log);
    }

    /**
     * 发送socket消息
     */
    public void sendSocketMessage(String message) {
        if (TextUtils.isEmpty(message.trim())) {
            return;
        }
        MsgDataBean msgDataBean = new MsgDataBean(message);
        if (mManager != null) {
            mManager.send(msgDataBean);
        }
    }
}
